use std::alloc::System;
use std::fmt;
use std::fmt::format;

use actix_web::{error, http::StatusCode, HttpResponse, Result};
use serde::Serialize;
use serde_json::Error;


#[derive(Debug, Serialize)]
pub enum RBlogError {
    ActixError(String),
    NotFound(String),
    InvalidInput(String),
    Unauthorized(String),
    DBError(String),
}


#[derive(Debug, Serialize)]
pub struct RBlogErrorResponse {
    code: i32,
    message: String,
    data: Option<String>,
}

impl RBlogError {
    fn error_response(&self) -> String {
        match self {
            RBlogError::ActixError(msg) => {
                println!("Server error occurred: {:?}", msg);
                "Internal server error".into()
            }
            RBlogError::NotFound(msg) => {
                println!("Not Found error: {:?}", msg);
                "Not Found".into()
            }
            RBlogError::InvalidInput(msg) => {
                println!("Invalid Input error: {:?}", msg);
                "Invalid Input".into()
            }
            RBlogError::Unauthorized(msg) => {
                println!("Unauthorized error: {:?}", msg);
                "Unauthorized error".into()
            }
            RBlogError::DBError(msg) => {
                println!("database error {:?}", msg);
                "Database error".into()
            }
        }
    }
}


impl error::ResponseError for RBlogError {
    fn status_code(&self) -> StatusCode {
        match self {
          RBlogError::ActixError(_msg) => StatusCode::INTERNAL_SERVER_ERROR,
          RBlogError::NotFound(_msg) => StatusCode::NOT_FOUND,
          RBlogError::InvalidInput(_msg) => StatusCode::BAD_REQUEST,
          RBlogError::Unauthorized(_msg) => StatusCode::UNAUTHORIZED,
            RBlogError::DBError(_msg) => StatusCode::INTERNAL_SERVER_ERROR,
        }
    }

    fn error_response(&self) -> HttpResponse {
        HttpResponse::build(self.status_code()).json(RBlogErrorResponse{
            code: -1,
            message: self.error_response(),
            data: None
        })
    }
}


impl fmt::Display for RBlogError {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "{}", self)
    }
}


impl From<actix_web::error::Error> for RBlogError {
  fn from(err: actix_web::error::Error) -> Self {
      RBlogError::ActixError(err.to_string())
  }
}

impl From<serde_json::Error> for RBlogError{
    fn from(err: serde_json::Error) -> Self {
        RBlogError::ActixError(err.to_string())
    }
}

impl From<rbatis::rbdc::Error> for RBlogError{
    fn from(err: rbatis::rbdc::Error) -> Self {
        RBlogError::DBError(err.to_string())
    }
    
}
